package xaj.scc.ast;

import java.util.Iterator;
import java.util.List;

import polyglot.ast.Node;
import polyglot.ext.jl.ast.Node_c;
import polyglot.util.CodeWriter;
import polyglot.util.CollectionUtil;
import polyglot.util.Position;
import polyglot.util.TypedList;
import polyglot.visit.NodeVisitor;
import polyglot.visit.PrettyPrinter;

public class Production_c extends Node_c implements Production {

	private String nonTerminal;
	private List<ProductionElement> elements;
	
	public Production_c(Position pos, String nonTerminal, List<ProductionElement> list) {
		super(pos);
		this.nonTerminal = nonTerminal;
		this.elements = list;
	}

	public String getLeftSide() {
		return nonTerminal;
	}

	public List<ProductionElement> getRightSide() {
		return elements;
	}

	public Production setLeftSide(String nonTerminal) {
		Production_c n = (Production_c) copy();
		n.nonTerminal = nonTerminal;
		return n;
	}

	public Production setRightSide(List<ProductionElement> list) {
		Production_c n = (Production_c) copy();
		n.elements = TypedList.copyAndCheck(list, ProductionElement.class, true);
		return n;
	}

	protected Production_c reconstruct(List<ProductionElement> l) {
		if(!CollectionUtil.equals(l, this.elements)) {
        	Production_c node = (Production_c) copy();
        	node.elements = TypedList.copyAndCheck(l, ProductionElement.class, true);
        	return node;
        }
        return this;
	}
	
	public Node visitChildren(NodeVisitor v) {
		List<ProductionElement> list = visitList(elements, v);
		return reconstruct(list);
	}
	
	public void prettyPrint(CodeWriter w, PrettyPrinter tr) {
		w.newline(4);
		w.begin(0);
		w.write(nonTerminal + " -> ");
		Iterator<ProductionElement> it = elements.iterator();
		ProductionElement p = it.next();
		p.prettyPrint(w, tr);
		while(it.hasNext()) {
			p = it.next();
			w.newline(2);
			w.begin(0);
			w.write("| ");
			if (p == null) {
				w.write("LAMBDA");
			} else {
				p.prettyPrint(w, tr);
			}
			w.end();
		}
		w.write(";");
		w.end();
	}
	
	
	@Override
	public void accept(Visitor v) {
		v.visitProduction(this);
	}
	
}
